#include "ssg_1_strategy.h"
#include "time_utils.hpp"

using namespace lt;

void ssg_1_strategy::on_init()
{
	subscrib_signal(_signal, this);
	use_custom_chain(true);
	_order_data = static_cast<persist_data*>(get_userdata(sizeof(persist_data)));

}

void ssg_1_strategy::on_ready()
{
	uint32_t trading_day = get_trading_day();
	_coming_to_close = make_datetime(trading_day, "14:58:00");
	if(_order_data->trading_day!=trading_day)
	{
		_order_data->trading_day = trading_day;
		_order_data->order_estid = INVALID_ESTID;
	}
	else
	{
		auto& order = get_order(_order_data->order_estid);
		if (order.est_id != INVALID_ESTID)
		{
			set_cancel_condition(order.est_id, [this,order](const tick_info& tick)->bool {

				if (tick.time - order.create_time > _cancel_second)
				{
					return true;
				}
				if (tick.time > _coming_to_close)
				{
					return true;
				}
				return false;
				});
		}
		else
		{
			_order_data->order_estid = INVALID_ESTID;
		}
	}
}

void ssg_1_strategy::on_signal(lt::sigid_t sigid, const code_t& code, lt::action_type type)
{
	LOG_INFO("sig_1_strategy on_signal %s %d \n", code.get_id(), type);
	
	if (!is_trading_ready())
	{
		LOG_DEBUG("sig_1_strategy is_trading_ready not ready %s\n", code.get_id());
		return;
	}
	if (get_last_time() > _coming_to_close)
	{
		//LOG_DEBUG("sig_1_strategy time > _coming_to_close %s %d %d\n", tick.id.get_id(), tick.time, _coming_to_close);
		return;
	}
	auto& tick = get_last_tick(code);
	if(tick.invalid())
	{
		return;
	}

	if (_order_data->order_estid == INVALID_ESTID)
	{
		const auto& pos = get_position(code);
		if (type == ACT_BEAR)
		{
			if(pos.long_position.volume - _open_once - get_open_long_pending(code) >= _min_position)
			{
				if (pos.long_position.usable() > 0)
				{
					_order_data->order_estid = sell_for_close(code, _open_once, tick.buy_price());
				}
			}
			
		}
		else if (type == ACT_BULL)
		{
			if (pos.long_position.volume + _open_once + get_open_long_pending(code) <= _max_position)
			{
				_order_data->order_estid = buy_for_open(code, _open_once, tick.sell_price());
			}
		}
	}
}



void ssg_1_strategy::on_entrust(const order_info& order)
{
	LOG_INFO("emg_2_strategy on_entrust : %llu %s %d %d %f %d/%d\n", order.est_id, order.code,order.direction,order.offset,order.price, order.last_volume,order.total_volume);

	if (_order_data->order_estid == order.est_id)
	{
		set_cancel_condition(order.est_id, [this,&order](const tick_info& tick)->bool {

			if (tick.time - order.create_time > _cancel_second)
			{
				return true;
			}
			if (tick.time > _coming_to_close)
			{
				return true;
			}
			return false;
			});
	}
}


void ssg_1_strategy::on_trade(estid_t localid, const code_t& code, offset_type offset, direction_type direction, double_t price, uint32_t volume)
{
	LOG_INFO("ssg_1_strategy on_trade : %llu %s %d %d %f %d\n", localid, code, direction, offset, price, volume);
	if (localid == _order_data->order_estid)
	{
		_order_data->order_estid = INVALID_ESTID;
	}
	
}

void ssg_1_strategy::on_cancel(estid_t localid, const code_t& code, offset_type offset, direction_type direction, double_t price, uint32_t cancel_volume,uint32_t total_volume)
{
	LOG_INFO("ssg_1_strategy on_cancel : %llu %s %d %d %f %d\n", localid, code, direction, offset, price, cancel_volume);
	if (localid == _order_data->order_estid)
	{
		_order_data->order_estid = INVALID_ESTID;
	}
}

void ssg_1_strategy::on_error(error_type type, estid_t localid, const uint32_t error)
{
	LOG_ERROR("ssg_1_strategy on_error : %llu %d \n", localid, error);
	if(type == ET_PLACE_ORDER)
	{
		if (localid == _order_data->order_estid)
		{
			_order_data->order_estid = INVALID_ESTID;
		}
	}
	else
	{
		auto& order = get_order(_order_data->order_estid);
		if (order.est_id == INVALID_ESTID)
		{
			_order_data->order_estid = INVALID_ESTID;
		}
	}
	
}
void ssg_1_strategy::on_destory()
{
	unsubscrib_signal(_signal, this);
}
